package com.insight.modules.cas.util;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.cert.X509Certificate;

public class CASServiceUtil {

    public static void main(String[] args) {
        // CAS服务验证地址
        String serviceUrl = "https://localhost:8443/cas/p3/serviceValidate";
        // 需要访问的服务地址
        String service = "http://localhost:3003/user/login";
        // 服务票据(Service Ticket)，通常由CAS认证中心颁发
        String ticket = "ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3";

        // 调用验证方法，获取验证结果
        String res = getSTValidate(serviceUrl, ticket, service);

        // 打印验证结果
        System.out.println("---------res-----" + res);
    }

    /**
     * 验证服务票据ST(Service Ticket)的有效性
     *
     * @param url     CAS服务验证接口地址
     * @param st      服务票据(Service Ticket)，由CAS服务颁发给客户端
     * @param service 申请服务票据时的服务地址，需与CAS一致
     * @return 如果验证成功，返回CAS响应内容字符串；验证失败或异常则返回空字符串
     */
    public static String getSTValidate(String url, String st, String service) {
        try {
            if (url == null || st == null || service == null) {
                return "";
            }
            url = url + "?service=" + service + "&ticket=" + st;
            CloseableHttpClient httpclient = createHttpClientWithNoSsl();
            if (httpclient == null) {
                return "";
            }
            HttpGet httpget = new HttpGet(url);
            HttpResponse response = httpclient.execute(httpget);
            String res = readResponse(response);
            return res == null ? null : (res == "" ? null : res);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 读取HttpResponse的响应体内容，将其转换为字符串返回
     *
     * @param response HttpResponse对象
     * @return 响应体字符串
     * @throws IOException 读取响应体异常
     */
    private static String readResponse(HttpResponse response) throws IOException {
        // 使用try-with-resources自动关闭输入流，避免资源泄漏
        try (BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
            StringBuilder result = new StringBuilder();
            String line;

            // 按行读取响应体内容
            while ((line = in.readLine()) != null) {
                result.append(line);
            }

            // 返回完整的响应字符串
            return result.toString();
        }
    }

    /**
     * 创建一个HttpClient实例，禁用SSL证书验证（信任所有证书）
     * 用于访问https协议且服务器证书为自签名或未被信任的情况
     *
     * @return CloseableHttpClient客户端实例
     * @throws Exception 创建过程中可能抛出的异常
     */
    private static CloseableHttpClient createHttpClientWithNoSsl() throws NoSuchAlgorithmException, KeyManagementException {
        // 定义一个不验证证书链的TrustManager实现
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    // 返回受信任的证书列表，这里返回空数组表示信任所有
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }

                    // 客户端证书检查，空实现表示不校验
                    @Override
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {}

                    // 服务器证书检查，空实现表示不校验
                    @Override
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                }
        };

        // 创建SSL上下文，使用TLS协议
        SSLContext ctx = SSLContext.getInstance("TLS");

        // 初始化SSL上下文，传入自定义的信任管理器和默认安全随机数生成器
        ctx.init(null, trustAllCerts, new java.security.SecureRandom());

        // 创建支持SSL的Socket工厂，使用上面定义的SSL上下文
        LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(ctx);

        // 构建HttpClient实例，设置为使用自定义的SSL Socket工厂
        return HttpClients.custom()
                .setSSLSocketFactory(sslSocketFactory)
                .build();
    }
}

